Background Information: Historic Home Owners’ Loan Corporation Neighborhood Appraisal Map
In 1934, the Federal Housing Administration created a financial mortgage system that rated mortgage risks for properties based on various criteria but was centered on race and ethnicity. This rating system propagated racial segregation that in many ways persists today.
The FHA Underwriting Handbook incorporated color-coded real estate investment maps that classified neighborhoods based on assumptions about a community, primarily their racial and ethnic composition, and not on the financial ability of the residents to satisfy the obligations of a mortgage loan. These maps, created by the Home Owners Loan Corporation (HOLC) were used to determine where mortgages could or could not be issued.
The neighborhoods were categoriezed into four types:
Type A : Best - newer or areas stil in demand
Type B : Still Desirable - areas expected to remain stable for many years
Type C : Definitely Declining - areas in transition
Type D : Hazardous - older areas considered risky
Neighborhoods shaded red were deemed too hazardous for federally-back loans. These “red-lined” neighborhoods were where most African American residents lived.
Many have argued tha the HOLC maps institutionalized discriminating lending practices which not only perpetuated racial segregation but also led to neighborhood disinvestment. Today, neighborhoods classified as Type C and Type D in 2934 make up the majority of neighborhoods in 2016 that are Areas of Concentrated Poverty where 50% or More are People of Color.
Purpose: Representing this historic map in digital form allows users to compare historically characterized neighborhoods in relation to current demographic trends.
Red-lining Data Time-Period: 01/01/1934
#GIS
library(sf) #create sf; extends data.frame-like objects with a simple feature list column
library(tmap) #use this for mapping
library(tmaptools) #use this for geocoding cities using OSM instead of Google (which requires API)
library(rnaturalearth) #to download U.S. borders and state lines
library(tigris) #use to download GIS TIGER shapefiles from the U.S. Census Bureau; The core TIGER/Line shapefiles do not include demographic data, but they do contain geographic entity codes (GEOIDs) that can be linked to the Census Bureau’s demographic data, available on data.census.gov.
#other
library(janitor) #clean data column names
library(tidyverse)
library(dplyr)
library(plyr)
library(forcats) #use for arranging or reordering factor levels
filter <- dplyr::filter
select <- dplyr::select
projcrs <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0" #set project CRS
#Minneapolis, Minnesota: Historic Home Owners' Loan Corporation Neighborhood Appraisal Map
#Download Link: https://resources.gisdata.mn.gov/pub/gdrs/data/pub/us_mn_state_metc/plan_historic_holc_appraisal/shp_plan_historic_holc_appraisal.zip
#Metadata: https://resources.gisdata.mn.gov/pub/gdrs/data/pub/us_mn_state_metc/plan_historic_holc_appraisal/metadata/metadata.html
rl <- read_sf("HistoricHOLCNeighborhoodAppraisal.shp")
#Log of Freedome of Press violation incidents during BLM protests in the U.S. -- maintained by PressFreedomTracker.US
#Download Link: https://docs.google.com/spreadsheets/d/1zk9oFDJ3Ocbz80Z1ISSW4Sd5xv1vQTj_tF8KCbPsZxs/edit#gid=0
fop <- read_csv("FreedomOfPress.csv") %>%
clean_names()
# MN state outline
MNstate_lines <- tigris::states(cb = TRUE) %>% #If cb is set to TRUE, download a generalized (1:500k) states file. Defaults to FALSE (the most detailed TIGER/Line file)
subset(NAME == "Minnesota")
plot(MNstate_lines)
MNstate_lines_sf <- st_as_sf(MNstate_lines)
#st_write(MNstate_lines_sf, "MNstate_lines.shp")
# MN county lines: this can be used as is within tmap-- don't nedd to convert unless you want to do additional analysis
MNcounty_lines <- tigris::counties(state = "MN", cb = TRUE)
plot(MNcounty_lines)
# if you want to save it as a shapefile for export
MNcounties_sf <- sf::st_as_sf(MNcounty_lines)
#plot(MNcounties_sf)
#st_write(MNcounties_sf, "MNcounty_lines.shp")
# unique(rl$HSG_SCALE) #looking at neighborhood categories
# [1] "Undeveloped" "Still Desirable" "Hazardous" "Definitely Declining" "Best"
# [6] "Park / Open Space" "Business and Industrial" "Uncertain" "Open Water"
rl_cats <- rl %>%
#mutate(cats = HSG_SCALE) %>%
dplyr::rename(cats = HSG_SCALE)
#reducing classification categories
rl_cats$cats <- plyr::revalue(rl_cats$cats, c("Undeveloped"="Other"))
rl_cats$cats <- plyr::revalue(rl_cats$cats, c("Business and Industrial"="Other"))
rl_cats$cats <- plyr::revalue(rl_cats$cats, c("Open Water"="Other"))
rl_cats$cats <- plyr::revalue(rl_cats$cats, c("Park / Open Space"="Other"))
rl_cats$cats[is.na(rl_cats$cats)] <- c("Other")
#reorder factor levels
cat_order <- c("Best", "Still Desirable", "Definitely Declining", "Other", "Hazardous")
rl_ordered <- rl_cats %>%
mutate(cats = factor(cats, levels = cat_order)) %>%
arrange(cats) #reorder best -> least
#create a bounding box for the redlining area (use to crop other shapes)
#write wrangled data into new csv to share with TidyTuesday
write_csv(rl_ordered, "minneapolis_redlining.csv", append = FALSE, na = "NA")
# map will be saved in a variable of class tmap
redlining <- tm_shape(MNcounty_lines) + #county lines
tmap_options(basemaps = c(
Canvas = "Esri.WorldGrayCanvas",
Terrain = "Stamen.TerrainBackground",
Imagery = "Esri.WorldImagery"
),
overlays = c(Labels = paste0("http://services.arcgisonline.com/arcgis/rest/services/Canvas/", "World_Light_Gray_Reference/MapServer/tile/{z}/{y}/{x}")), alpha = 0.8) + #you need to specify this URL for basemaps to show
tm_borders(col = "blue", alpha = 0.4, lwd = 1) +
tm_shape(MNstate_lines) + #state lines
tm_borders(col = "magenta3", alpha = 0.2, lwd = 2) +
tm_shape(rl_ordered) + #red-lining catergorization of each neighborhood in Minneapolis and St. Paul
tm_polygons("cats",
palette = "-Spectral",
border.alpha = 0.3,
id = "cats",
popup.vars = c("Category: " = "cats"),
title = "Redlining Areas in Minneapolis") +
tm_layout(title = "Redlining in Minneapolis",
title.size = 1,
legend.outside.size = 0.5
) +
tm_legend(legend.position = c("left", "bottom")) +
tm_scale_bar(breaks = c(0, 100, 200), position = c("right", "bottom"), color.dark = "grey70", color.light = "white") +
tmap_mode("view")
redlining